package cn.angis.system.controller;


import cn.angis.common.constant.Constant;
import cn.angis.common.model.R;
import cn.angis.common.util.StringU;
import cn.angis.db.controller.RBaseController;
import cn.angis.db.model.PageModel;
import cn.angis.db.model.PageOfResult;
import cn.angis.system.dto.output.LoginOutput;
import cn.angis.system.model.AuthSessionAnalysisResult;
import cn.angis.system.util.AuthUtil;
import cn.dev33.satoken.session.SaSession;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaFoxUtil;
import org.apache.commons.lang3.time.DateUtils;
import org.noear.snack.ONode;
import org.noear.solon.annotation.Controller;
import org.noear.solon.annotation.Get;
import org.noear.solon.annotation.Mapping;
import org.noear.solon.annotation.Post;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 在线用户监控
 *
 * @author ruoyi
 */
@Controller
@Mapping("/monitor/online/")
public class UserOnlineController extends RBaseController {

    @Mapping("list")
    @Get
    public R<PageOfResult<LoginOutput>> list(PageModel pageModel) {
        List<LoginOutput> list = new ArrayList<>();
        // 获取所有登录的用户ids
        List<String> logIds = StpUtil.searchSessionId("", 0, -1, false);
        // 便利获取登录信息
        SaSession session = null;
        for (int i = (pageModel.getCurrent() - 1) * pageModel.getSize(), len = Math.min(pageModel.getSize() + i, logIds.size()); i < len; i++) {
            session = StpUtil.getSessionBySessionId(logIds.get(i));
            list.add(AuthUtil.getUserBySession(session));
        }
        PageOfResult pageOfResult = new PageOfResult();
        pageOfResult.setCurrent(pageModel.getCurrent());
        pageOfResult.setSize(pageModel.getSize());
        pageOfResult.setTotal(logIds.size());
        pageOfResult.setRecords(list);
        return success(pageOfResult);
    }

    /**
     * 强退用户
     */
    @Mapping("{tokenId}")
    @Post
    public R<String> forceLogout(String tokenId) {
        StpUtil.kickoutByTokenValue(tokenId);
        return success();
    }

    public AuthSessionAnalysisResult analysis() {
        AuthSessionAnalysisResult authSessionAnalysisResult = new AuthSessionAnalysisResult();
        List<ONode> sessionListB = StpUtil.searchSessionId("", -1, -1, false).stream().map(sessionId -> {
            ONode jsonObject = new ONode();
            String userId = Arrays.stream(StringU.split(sessionId, StringU.COLON)).toList().get(3);
            SaSession saSession = StpUtil.getSessionByLoginId(userId, false);
            int tokenCount = saSession.getTerminalList().size();
            long createTime = saSession.getCreateTime();
            jsonObject.set("userId", userId);
            jsonObject.set("tokenCount", tokenCount);
            jsonObject.set("createTime", new Date(createTime));
            return jsonObject;
        }).collect(Collectors.toList());

        List<ONode> sessionListC = StpUtil.searchSessionId("", -1, -1,  false).stream().map(sessionId -> {
            ONode jsonObject = new ONode();
            String userId = Arrays.stream(StringU.split(sessionId, StringU.COLON)).toList().get(3);
            SaSession saSession = StpUtil.getSessionByLoginId(userId, false);
            int tokenCount = saSession.getTerminalList().size();
            long createTime = saSession.getCreateTime();
            jsonObject.set("userId", userId);
            jsonObject.set("tokenCount", tokenCount);
            jsonObject.set("createTime", new Date(createTime));
            return jsonObject;
        }).collect(Collectors.toList());

        List<Integer> tokenCountList = new ArrayList<>();
        tokenCountList.addAll(sessionListB.stream().map(jsonObject -> jsonObject.get("tokenCount").getInt()).collect(Collectors.toList()));
        tokenCountList.addAll(sessionListC.stream().map(jsonObject -> jsonObject.get("tokenCount").getInt()).collect(Collectors.toList()));
        Collections.sort(tokenCountList, Comparator.comparingInt(Integer::intValue));
        int currentSessionTotalCount = sessionListB.size() + sessionListC.size();
        authSessionAnalysisResult.setCurrentSessionTotalCount(String.valueOf(currentSessionTotalCount));
        authSessionAnalysisResult.setMaxTokenCount(String.valueOf(tokenCountList.get(tokenCountList.size() - 1)));
        List<Date> sessionCreateTimeList = new ArrayList<>();
        sessionCreateTimeList.addAll(sessionListB.stream().map(jsonObject -> jsonObject.get("createTime").getDate()).collect(Collectors.toList()));
        sessionCreateTimeList.addAll(sessionListC.stream().map(jsonObject -> jsonObject.get("createTime").getDate()).collect(Collectors.toList()));
        Date oneHourAgo = DateUtils.addHours(new Date(), -1);
        authSessionAnalysisResult.setOneHourNewlyAdded(String.valueOf(sessionCreateTimeList.stream().filter(date -> DateUtils.truncatedCompareTo(oneHourAgo, date, Calendar.LONG) <= 0).count()));
        authSessionAnalysisResult.setProportionOfBAndC(sessionListB.size() + StringU.SLASH + sessionListC.size());
        return authSessionAnalysisResult;
    }
}
